//
// Created by zerax on 2020/10/27.
//

#include "texture.hh"

Texture::~Texture() {
    if (m_rawHandle) glDeleteTextures(1, &m_rawHandle);
}

Texture::Texture(int width, int height, const void *pixels, TextureFormat fmt) {
    glGenTextures(1, &m_rawHandle);

    glBindTexture(GL_TEXTURE_2D, m_rawHandle);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    unsigned int format;
    switch (fmt) {
        case TextureFormat::RGB:
            format = GL_RGB;
            break;
        case TextureFormat::RGBA:
            format = GL_RGBA;
            break;
        default:
            format = GL_RGB;
    }

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, format, GL_UNSIGNED_BYTE, pixels);
    glBindTexture(GL_TEXTURE_2D, 0);
}

Texture::Texture(Texture&& texture) noexcept {
    m_rawHandle = texture.m_rawHandle;
    texture.m_rawHandle = 0;
}

Texture& Texture::operator=(Texture&& texture) noexcept {
    m_rawHandle = texture.m_rawHandle;
    texture.m_rawHandle = 0;
    return *this;
}

void Texture::setBindPoint(const char *name, unsigned int bindPosition) {
    m_bindPoint = std::make_pair(name, bindPosition);
}

void Texture::bind(const Shader& shader) const {
    glActiveTexture(GL_TEXTURE0 + m_bindPoint.second);
    shader.setUniform(m_bindPoint.first, m_bindPoint.second);
    glBindTexture(GL_TEXTURE_2D, m_rawHandle);
}

void Texture::unbind() {
    glBindTexture(GL_TEXTURE_2D, 0);
}


